package com.byx.chatclient.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;

import androidx.annotation.Nullable;

/**
 * LetterIndexView
 *
 * @author Superb
 * @date 2021/3/26 17:05
 */
public class LetterIndexView extends View {
    private Paint mPaint1;
    private Paint mPaint2;
    /**
     * 26个字母和2个符号
      */
    public static String[] letters = {"↑","A", "B", "C", "D", "E", "F", "G", "H", "I",
            "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
            "W", "X", "Y", "Z", "#"};
    private int height;
    private int mWidth;
    private String currentLetter;
    private OnTouchSelectListener mListener;

    /**
     * Simple constructor to use when creating a view from code.
     *
     * @param context The Context the view is running in, through which it can
     *                access the current theme, resources, etc.
     */
    public LetterIndexView(Context context) {
        super(context);
    }

    /**
     * Constructor that is called when inflating a view from XML. This is called
     * when a view is being constructed from an XML file, supplying attributes
     * that were specified in the XML file. This version uses a default style of
     * 0, so the only attribute values applied are those in the Context's Theme
     * and the given AttributeSet.
     *
     * <p>
     * The method onFinishInflate() will be called after all children have been
     * added.
     *
     * @param context The Context the view is running in, through which it can
     *                access the current theme, resources, etc.
     * @param attrs   The attributes of the XML tag that is inflating the view.
     * @see # View(Context, AttributeSet, int)
     */
    public LetterIndexView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * Perform inflation from XML and apply a class-specific base style from a
     * theme attribute. This constructor of View allows subclasses to use their
     * own base style when they are inflating. For example, a Button class's
     * constructor would call this version of the super class constructor and
     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
     * allows the theme's button style to modify all of the base view attributes
     * (in particular its background) as well as the Button class's attributes.
     *
     * @param context      The Context the view is running in, through which it can
     *                     access the current theme, resources, etc.
     * @param attrs        The attributes of the XML tag that is inflating the view.
     * @param defStyleAttr An attribute in the current theme that contains a
     *                     reference to a style resource that supplies default values for
     *                     the view. Can be 0 to not look for defaults.
     * @see # View(Context, AttributeSet)
     */
    public LetterIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    /**
     * Perform inflation from XML and apply a class-specific base style from a
     * theme attribute or style resource. This constructor of View allows
     * subclasses to use their own base style when they are inflating.
     * <p>
     * When determining the final value of a particular attribute, there are
     * four inputs that come into play:
     * <ol>
     * <li>Any attribute values in the given AttributeSet.
     * <li>The style resource specified in the AttributeSet (named "style").
     * <li>The default style specified by <var>defStyleAttr</var>.
     * <li>The default style specified by <var>defStyleRes</var>.
     * <li>The base values in this theme.
     * </ol>
     * <p>
     * Each of these inputs is considered in-order, with the first listed taking
     * precedence over the following ones. In other words, if in the
     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
     * , then the button's text will <em>always</em> be black, regardless of
     * what is specified in any of the styles.
     *
     * @param context      The Context the view is running in, through which it can
     *                     access the current theme, resources, etc.
     * @param attrs        The attributes of the XML tag that is inflating the view.
     * @param defStyleAttr An attribute in the current theme that contains a
     *                     reference to a style resource that supplies default values for
     *                     the view. Can be 0 to not look for defaults.
     * @param defStyleRes  A resource identifier of a style resource that
     *                     supplies default values for the view, used only if
     *                     defStyleAttr is 0 or can not be found in the theme. Can be 0
     *                     to not look for defaults.
     * @see # View(Context, AttributeSet, int)
     */
    public LetterIndexView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    private void init() {
        mPaint1 = new Paint();
        mPaint1.setAntiAlias(true);//抗锯齿
        mPaint1.setTextSize(sp2px(10));//文字 sp转px
        mPaint1.setColor(Color.BLACK);

        mPaint2 = new Paint();
        mPaint2.setAntiAlias(true);
        mPaint2.setTextSize(sp2px(10));
        mPaint2.setColor(Color.RED);
    }

    public int sp2px(float spValue) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue,getResources().getDisplayMetrics());
    }

    /**
     * Implement this to do your drawing.
     *
     * @param canvas the canvas on which the background will be drawn
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //单个字母的高度
        int letterHeight = height / letters.length;
        for (int i = 0; i < letters.length; i++) {
            //单个字母的宽度
            float measureWidth = mPaint1.measureText(letters[i]);
            int dy = (int) (letterHeight * i + letterHeight - measureWidth / 2);
            int dx = (int) (mWidth / 2 - measureWidth / 2);

            canvas.drawText(letters[i], dx, dy, mPaint1);
            //判断字符是不是选中的
            if (letters[i].equals(currentLetter)) {
                canvas.drawText(letters[i], dx, dy, mPaint2);
            }
        }
    }

    /**
     * Implement this method to handle touch screen motion events.
     * <p>
     * If this method is used to detect click actions, it is recommended that
     * the actions be performed by implementing and calling
     * {@link #performClick()}. This will ensure consistent system behavior,
     * including:
     * <ul>
     * <li>obeying click sound preferences
     * <li>dispatching OnClickListener calls
     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
     * accessibility features are enabled
     * </ul>
     *
     * @param event The motion event.
     * @return True if the event was handled, false otherwise.
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        //这里需要判断一下，滑动的区域是不是在我们26 个字母的范围内。
        if ((event.getY() / height) * letters.length < 0 || (event.getY() / height) * letters.length > letters.length) {
            return false;
        }
        switch (event.getAction()) {
            //监听按下和移动事件
            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_MOVE:
                //获取当前字母（按下或移动的高度除总高度乘以总个数=按下或移动的数组的下标）
                currentLetter = letters[(int) ((event.getY() / height) * letters.length)];
                //回调
                mListener.touch(true,currentLetter);
                //刷新界面，就是重新调用 Draw 方法
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                //抬起的时候给下标设置 为空
                currentLetter = "";
                //延时回调
                this.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mListener.touch(false,currentLetter);
                    }
                },1500);
                invalidate();
                break;
            default:
                break;
        }
        return true;
    }

    public void setOnTouchSelectListener(OnTouchSelectListener listener) {
        mListener = listener;
    }

    public interface OnTouchSelectListener {
        void touch(boolean isTouch,String select);
    }
}
